package com.obggtc.picture.service.impl;

import com.alibaba.fastjson.JSON;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.obggtc.picture.entity.MediaFile;
import com.obggtc.picture.mapper.MediaFileMapper;
import com.obggtc.picture.service.MediaFileService;
import com.obggtc.picture.utils.RedisUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.List;

/**
 * 媒体文件服务实现类
 */
@Service
public class MediaFileServiceImpl extends ServiceImpl<MediaFileMapper, MediaFile> implements MediaFileService {
    
    private static final Logger log = LoggerFactory.getLogger(MediaFileServiceImpl.class);
    
    @Autowired
    private MediaFileMapper mediaFileMapper;
    
    @Autowired
    private RedisUtils redisUtils;
    
    // Redis Key前缀
    private static final String MEDIA_INFO_PREFIX = "media:info:";
    private static final String USER_MEDIA_LIST_PREFIX = "media:user:";
    private static final String RECENT_MEDIA_PREFIX = "media:recent:";
    private static final String HOT_MEDIA_PREFIX = "media:hot:";
    private static final String TAG_MEDIA_PREFIX = "media:tag:";
    private static final String MEDIA_VIEW_COUNT_PREFIX = "media:view:";
    
    // 缓存时间（秒）
    private static final long MEDIA_INFO_CACHE_TIME = 3600; // 1小时
    private static final long LIST_CACHE_TIME = 1800; // 30分钟
    private static final long HOT_CACHE_TIME = 3600; // 1小时
    private static final long VIEW_COUNT_CACHE_TIME = 86400; // 24小时
    
    @Override
    public boolean saveMediaFile(MediaFile mediaFile) {
        try {
            boolean result = this.save(mediaFile);
            if (result) {
                // 缓存媒体文件信息
                String cacheKey = MEDIA_INFO_PREFIX + mediaFile.getFileId();
                redisUtils.set(cacheKey, JSON.toJSONString(mediaFile), MEDIA_INFO_CACHE_TIME);
                
                // 清除相关列表缓存
                clearListCache(mediaFile.getUploader(), mediaFile.getFileType());
                
                log.info("媒体文件保存成功: {}", mediaFile.getFileId());
            }
            return result;
        } catch (Exception e) {
            log.error("保存媒体文件失败", e);
            return false;
        }
    }
    
    @Override
    public MediaFile getMediaFileByFileId(String fileId) {
        // 先从缓存获取
        String cacheKey = MEDIA_INFO_PREFIX + fileId;
        Object cached = redisUtils.get(cacheKey);
        if (cached != null) {
            try {
                return JSON.parseObject(cached.toString(), MediaFile.class);
            } catch (Exception e) {
                log.warn("解析缓存的媒体文件信息失败: {}", fileId, e);
                redisUtils.del(cacheKey);
            }
        }
        
        // 缓存未命中，从数据库查询
        QueryWrapper<MediaFile> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("file_id", fileId)
                   .eq("status", MediaFile.STATUS_NORMAL);
        
        MediaFile mediaFile = this.getOne(queryWrapper);
        if (mediaFile != null) {
            // 更新缓存
            redisUtils.set(cacheKey, JSON.toJSONString(mediaFile), MEDIA_INFO_CACHE_TIME);
        }
        
        return mediaFile;
    }
    
    @Override
    public IPage<MediaFile> getUserMediaFiles(String uploader, Integer fileType, int page, int size) {
        // 构建缓存Key
        String cacheKey = USER_MEDIA_LIST_PREFIX + uploader + ":" + 
                         (fileType != null ? fileType : "all") + ":" + page + ":" + size;
        
        // 先从缓存获取
        Object cached = redisUtils.get(cacheKey);
        if (cached != null) {
            try {
                // 创建一个新的Page对象来解析结果
                @SuppressWarnings("unchecked")
                Page<MediaFile> cachedPage = JSON.parseObject(cached.toString(), Page.class);
                // 重新解析records为MediaFile对象
                List<MediaFile> records = JSON.parseArray(JSON.toJSONString(cachedPage.getRecords()), MediaFile.class);
                cachedPage.setRecords(records);
                
                // 如果有有效数据，返回缓存结果
                if (cachedPage.getTotal() > 0 || !records.isEmpty()) {
                    log.debug("从缓存获取用户媒体文件列表: {}, total: {}", uploader, cachedPage.getTotal());
                    return cachedPage;
                }
            } catch (Exception e) {
                log.warn("解析缓存的用户媒体文件列表失败: {}", uploader, e);
                redisUtils.del(cacheKey);
            }
        }
        
        // 缓存未命中，从数据库查询
        Page<MediaFile> pageObj = new Page<>(page, size);
        log.info("执行数据库查询 - uploader: {}, fileType: {}, page: {}, size: {}", uploader, fileType, page, size);
        
        IPage<MediaFile> result = mediaFileMapper.selectUserMediaFiles(
            pageObj, uploader, fileType, MediaFile.STATUS_NORMAL);
        
        // 详细调试信息
        if (result != null) {
            log.info("数据库查询用户媒体文件列表结果 - uploader: {}, fileType: {}, total: {}, records: {}, pages: {}", 
                uploader, fileType, result.getTotal(), result.getRecords().size(), result.getPages());
            
            // 只有当有数据时才缓存
            if (result.getTotal() > 0 || !result.getRecords().isEmpty()) {
                redisUtils.set(cacheKey, JSON.toJSONString(result), LIST_CACHE_TIME);
            }
        } else {
            log.warn("数据库查询返回null结果 - uploader: {}, fileType: {}", uploader, fileType);
        }
        
        return result;
    }
    
    @Override
    public IPage<MediaFile> getMediaFilesByTag(String tag, Integer fileType, int page, int size) {
        // 构建缓存Key
        String cacheKey = TAG_MEDIA_PREFIX + tag + ":" + 
                         (fileType != null ? fileType : "all") + ":" + page + ":" + size;
        
        // 先从缓存获取
        Object cached = redisUtils.get(cacheKey);
        if (cached != null) {
            try {
                // 创建一个新的Page对象来解析结果
                @SuppressWarnings("unchecked")
                Page<MediaFile> cachedPage = JSON.parseObject(cached.toString(), Page.class);
                // 重新解析records为MediaFile对象
                List<MediaFile> records = JSON.parseArray(JSON.toJSONString(cachedPage.getRecords()), MediaFile.class);
                cachedPage.setRecords(records);
                
                // 如果有有效数据，返回缓存结果
                if (cachedPage.getTotal() > 0 || !records.isEmpty()) {
                    log.debug("从缓存获取标签媒体文件列表: {}, total: {}", tag, cachedPage.getTotal());
                    return cachedPage;
                }
            } catch (Exception e) {
                log.warn("解析缓存的标签媒体文件列表失败: {}", tag, e);
                redisUtils.del(cacheKey);
            }
        }
        
        // 缓存未命中，从数据库查询
        Page<MediaFile> pageObj = new Page<>(page, size);
        log.debug("执行标签查询 - tag: {}, fileType: {}, page: {}, size: {}", tag, fileType, page, size);
        
        IPage<MediaFile> result = mediaFileMapper.selectMediaFilesByTag(
            pageObj, tag, fileType, MediaFile.STATUS_NORMAL);
        
        // 详细调试信息
        if (result != null) {
            log.info("标签查询结果 - tag: {}, fileType: {}, total: {}, records: {}, pages: {}", 
                tag, fileType, result.getTotal(), result.getRecords().size(), result.getPages());
            
            // 只有当有数据时才缓存
            if (result.getTotal() > 0 || !result.getRecords().isEmpty()) {
                redisUtils.set(cacheKey, JSON.toJSONString(result), LIST_CACHE_TIME);
            }
        } else {
            log.warn("标签查询返回null结果 - tag: {}, fileType: {}", tag, fileType);
        }
        
        return result;
    }
    
    @Override
    public List<MediaFile> getRecentMediaFiles(Integer fileType, int count) {
        // 构建缓存Key
        String cacheKey = RECENT_MEDIA_PREFIX + (fileType != null ? fileType : "all") + ":" + count;
        
        // 先从缓存获取
        Object cached = redisUtils.get(cacheKey);
        if (cached != null) {
            try {
                return JSON.parseArray(cached.toString(), MediaFile.class);
            } catch (Exception e) {
                log.warn("解析缓存的最近媒体文件列表失败", e);
                redisUtils.del(cacheKey);
            }
        }
        
        // 缓存未命中，从数据库查询
        List<MediaFile> result = mediaFileMapper.selectRecentMediaFiles(
            fileType, MediaFile.STATUS_NORMAL, count);
        
        // 更新缓存
        if (result != null) {
            redisUtils.set(cacheKey, JSON.toJSONString(result), LIST_CACHE_TIME);
        }
        
        return result;
    }
    
    @Override
    public List<MediaFile> getHotMediaFiles(Integer fileType, int count) {
        // 构建缓存Key
        String cacheKey = HOT_MEDIA_PREFIX + (fileType != null ? fileType : "all") + ":" + count;
        
        // 先从缓存获取
        Object cached = redisUtils.get(cacheKey);
        if (cached != null) {
            try {
                return JSON.parseArray(cached.toString(), MediaFile.class);
            } catch (Exception e) {
                log.warn("解析缓存的热门媒体文件列表失败", e);
                redisUtils.del(cacheKey);
            }
        }
        
        // 缓存未命中，从数据库查询
        List<MediaFile> result = mediaFileMapper.selectHotMediaFiles(
            fileType, MediaFile.STATUS_NORMAL, count);
        
        // 更新缓存
        if (result != null) {
            redisUtils.set(cacheKey, JSON.toJSONString(result), HOT_CACHE_TIME);
        }
        
        return result;
    }
    
    @Override
    public long incrementViewCount(String fileId) {
        // 先更新数据库
        mediaFileMapper.incrementViewCount(fileId);
        
        // 更新Redis中的观看次数
        String cacheKey = MEDIA_VIEW_COUNT_PREFIX + fileId;
        long count = redisUtils.incr(cacheKey, 1);
        
        // 设置过期时间
        if (count == 1) {
            redisUtils.expire(cacheKey, VIEW_COUNT_CACHE_TIME);
        }
        
        // 清除相关缓存
        clearMediaFileCache(fileId);
        
        return count;
    }
    
    @Override
    public long incrementDownloadCount(String fileId) {
        // 更新数据库
        mediaFileMapper.incrementDownloadCount(fileId);
        
        // 清除相关缓存
        clearMediaFileCache(fileId);
        
        // 获取最新的下载次数
        MediaFile mediaFile = getMediaFileByFileId(fileId);
        return mediaFile != null ? mediaFile.getDownloadCount() : 0;
    }
    
    @Override
    public boolean deleteMediaFile(String fileId, String uploader) {
        try {
            // 验证文件所有权
            MediaFile mediaFile = getMediaFileByFileId(fileId);
            if (mediaFile == null) {
                log.warn("媒体文件不存在: {}", fileId);
                return false;
            }
            
            if (!uploader.equals(mediaFile.getUploader())) {
                log.warn("用户 {} 尝试删除不属于自己的文件: {}", uploader, fileId);
                return false;
            }
            
            // 逻辑删除
            UpdateWrapper<MediaFile> updateWrapper = new UpdateWrapper<>();
            updateWrapper.eq("file_id", fileId)
                        .set("status", MediaFile.STATUS_DELETED);
            
            boolean result = this.update(updateWrapper);
            if (result) {
                // 清除所有相关缓存
                clearMediaFileCache(fileId);
                clearListCache(uploader, mediaFile.getFileType());
                
                log.info("媒体文件删除成功: {}", fileId);
            }
            
            return result;
        } catch (Exception e) {
            log.error("删除媒体文件失败: {}", fileId, e);
            return false;
        }
    }
    
    @Override
    public long countUserMediaFiles(String uploader, Integer fileType) {
        long count = mediaFileMapper.countUserMediaFiles(uploader, fileType, MediaFile.STATUS_NORMAL);
        log.debug("统计用户媒体文件数量 - uploader: {}, fileType: {}, count: {}", uploader, fileType, count);
        return count;
    }
    
    @Override
    public void clearMediaFileCache(String fileId) {
        // 清除单个文件信息缓存
        String infoCacheKey = MEDIA_INFO_PREFIX + fileId;
        redisUtils.del(infoCacheKey);
        
        // 清除观看次数缓存
        String viewCacheKey = MEDIA_VIEW_COUNT_PREFIX + fileId;
        redisUtils.del(viewCacheKey);
        
        log.debug("清除媒体文件缓存: {}", fileId);
    }
    
    @Override
    public void refreshHotMediaFilesCache() {
        try {
            // 清除所有热门文件缓存
            String pattern = HOT_MEDIA_PREFIX + "*";
            redisUtils.del(pattern);
            
            log.info("热门媒体文件缓存已刷新");
        } catch (Exception e) {
            log.error("刷新热门媒体文件缓存失败", e);
        }
    }
    
    /**
     * 清除用户列表相关缓存
     */
    private void clearListCache(String uploader, Integer fileType) {
        try {
            // 清除用户文件列表缓存
            String userPattern = USER_MEDIA_LIST_PREFIX + uploader + "*";
            redisUtils.del(userPattern);
            
            // 清除最近上传缓存
            String recentPattern = RECENT_MEDIA_PREFIX + "*";
            redisUtils.del(recentPattern);
            
            // 清除热门文件缓存
            String hotPattern = HOT_MEDIA_PREFIX + "*";
            redisUtils.del(hotPattern);
            
            log.debug("清除用户列表缓存: {}", uploader);
        } catch (Exception e) {
            log.error("清除列表缓存失败", e);
        }
    }
}
